﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.MountAndBlade.View.CraftedDataView
// Assembly: TaleWorlds.MountAndBlade.View, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 61152EB8-513B-4D4A-8AC0-0D1465C6CF6C
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\Modules\Native\bin\Win64_Shipping_Client\TaleWorlds.MountAndBlade.View.dll

using System.Collections.Generic;
using TaleWorlds.Core;
using TaleWorlds.DotNet;
using TaleWorlds.Engine;
using TaleWorlds.Library;

#nullable disable
namespace TaleWorlds.MountAndBlade.View
{
  public class CraftedDataView
  {
    private MetaMesh _weaponMesh;
    private MetaMesh _holsterMesh;
    private MetaMesh _holsterMeshWithWeapon;
    private MetaMesh _nonBatchedWeaponMesh;
    private MetaMesh _nonBatchedHolsterMesh;
    private MetaMesh _nonBatchedHolsterMeshWithWeapon;

    public WeaponDesign CraftedData { get; private set; }

    public MetaMesh WeaponMesh
    {
      get
      {
        return !((NativeObject) this._weaponMesh != (NativeObject) null) || !this._weaponMesh.HasVertexBufferOrEditDataOrPackageItem() ? (this._weaponMesh = this.GenerateWeaponMesh(true)) : this._weaponMesh;
      }
    }

    public MetaMesh HolsterMesh
    {
      get => this._holsterMesh ?? (this._holsterMesh = this.GenerateHolsterMesh());
    }

    public MetaMesh HolsterMeshWithWeapon
    {
      get
      {
        return !((NativeObject) this._holsterMeshWithWeapon != (NativeObject) null) || !this._holsterMeshWithWeapon.HasVertexBufferOrEditDataOrPackageItem() ? (this._holsterMeshWithWeapon = this.GenerateHolsterMeshWithWeapon(true)) : this._holsterMeshWithWeapon;
      }
    }

    public MetaMesh NonBatchedWeaponMesh
    {
      get
      {
        return this._nonBatchedWeaponMesh ?? (this._nonBatchedWeaponMesh = this.GenerateWeaponMesh(false));
      }
    }

    public MetaMesh NonBatchedHolsterMesh
    {
      get
      {
        return this._nonBatchedHolsterMesh ?? (this._nonBatchedHolsterMesh = this.GenerateHolsterMesh());
      }
    }

    public MetaMesh NonBatchedHolsterMeshWithWeapon
    {
      get
      {
        return this._nonBatchedHolsterMeshWithWeapon ?? (this._nonBatchedHolsterMeshWithWeapon = this.GenerateHolsterMeshWithWeapon(false));
      }
    }

    public CraftedDataView(WeaponDesign craftedData) => this.CraftedData = craftedData;

    public void Clear()
    {
      this._weaponMesh = (MetaMesh) null;
      this._holsterMesh = (MetaMesh) null;
      this._holsterMeshWithWeapon = (MetaMesh) null;
      this._nonBatchedWeaponMesh = (MetaMesh) null;
      this._nonBatchedHolsterMesh = (MetaMesh) null;
      this._nonBatchedHolsterMeshWithWeapon = (MetaMesh) null;
    }

    private MetaMesh GenerateWeaponMesh(bool batchMeshes)
    {
      return this.CraftedData.UsedPieces != null ? CraftedDataView.BuildWeaponMesh(this.CraftedData, 0.0f, false, batchMeshes) : (MetaMesh) null;
    }

    private MetaMesh GenerateHolsterMesh()
    {
      return this.CraftedData.UsedPieces != null ? CraftedDataView.BuildHolsterMesh(this.CraftedData) : (MetaMesh) null;
    }

    private MetaMesh GenerateHolsterMeshWithWeapon(bool batchMeshes)
    {
      return this.CraftedData.UsedPieces != null ? CraftedDataView.BuildHolsterMeshWithWeapon(this.CraftedData, 0.0f, batchMeshes) : (MetaMesh) null;
    }

    public static MetaMesh BuildWeaponMesh(
      WeaponDesign craftedData,
      float pivotDiff,
      bool pieceTypeHidingEnabledForHolster,
      bool batchAllMeshes)
    {
      CraftingTemplate template = craftedData.Template;
      MetaMesh metaMesh1 = MetaMesh.CreateMetaMesh();
      List<MetaMesh> metaMeshes = new List<MetaMesh>();
      List<MetaMesh> metaMeshList1 = new List<MetaMesh>();
      List<MetaMesh> metaMeshList2 = new List<MetaMesh>();
      foreach (PieceData buildOrder in template.BuildOrders)
      {
        if (!pieceTypeHidingEnabledForHolster || !template.IsPieceTypeHiddenOnHolster(buildOrder.PieceType))
        {
          WeaponDesignElement usedPiece = craftedData.UsedPieces[(int) buildOrder.PieceType];
          float piecePivotDistance = craftedData.PiecePivotDistances[(int) buildOrder.PieceType];
          if (usedPiece != null && usedPiece.IsValid && !float.IsNaN(piecePivotDistance))
          {
            MetaMesh copy = MetaMesh.GetCopy(usedPiece.CraftingPiece.MeshName);
            if (!batchAllMeshes)
              copy.ClearMeshesForOtherLods(0);
            MatrixFrame matrixFrame = new MatrixFrame(Mat3.Identity, piecePivotDistance * Vec3.Up);
            if (usedPiece.IsPieceScaled)
            {
              Vec3 scalingVector = usedPiece.CraftingPiece.FullScale ? Vec3.One * usedPiece.ScaleFactor : new Vec3(1f, 1f, usedPiece.ScaleFactor);
              matrixFrame.Scale(scalingVector);
            }
            copy.Frame = matrixFrame;
            if (copy.HasClothData())
              metaMeshList2.Add(copy);
            else
              metaMeshList1.Add(copy);
          }
        }
      }
      foreach (MetaMesh metaMesh2 in metaMeshList1)
      {
        if (batchAllMeshes)
          metaMeshes.Add(metaMesh2);
        else
          metaMesh1.MergeMultiMeshes(metaMesh2);
      }
      if (batchAllMeshes)
        metaMesh1.BatchMultiMeshesMultiple(metaMeshes);
      foreach (MetaMesh metaMesh3 in metaMeshList2)
      {
        metaMesh1.MergeMultiMeshes(metaMesh3);
        metaMesh1.AssignClothBodyFrom(metaMesh3);
      }
      metaMesh1.SetEditDataPolicy(EditDataPolicy.Keep_until_first_render);
      if (batchAllMeshes)
        metaMesh1.SetLodBias(1);
      MatrixFrame frame = metaMesh1.Frame;
      frame.Elevate(pivotDiff);
      metaMesh1.Frame = frame;
      return metaMesh1;
    }

    public static MetaMesh BuildHolsterMesh(WeaponDesign craftedData)
    {
      if (craftedData.Template.UseWeaponAsHolsterMesh)
        return (MetaMesh) null;
      BladeData bladeData = craftedData.UsedPieces[0].CraftingPiece.BladeData;
      if (craftedData.Template.AlwaysShowHolsterWithWeapon || string.IsNullOrEmpty(bladeData.HolsterMeshName))
        return (MetaMesh) null;
      float piecePivotDistance = craftedData.PiecePivotDistances[0];
      MetaMesh copy = MetaMesh.GetCopy(bladeData.HolsterMeshName, false);
      MatrixFrame frame = copy.Frame;
      frame.origin += new Vec3(z: piecePivotDistance);
      WeaponDesignElement usedPiece = craftedData.UsedPieces[0];
      if ((double) MathF.Abs(usedPiece.ScaledLength - usedPiece.CraftingPiece.Length) > 9.9999997473787516E-06)
      {
        Vec3 scalingVector = usedPiece.CraftingPiece.FullScale ? Vec3.One * usedPiece.ScaleFactor : new Vec3(1f, 1f, usedPiece.ScaleFactor);
        frame.Scale(scalingVector);
      }
      copy.Frame = frame;
      MetaMesh metaMesh = MetaMesh.CreateMetaMesh(bladeData.HolsterMeshName);
      metaMesh.MergeMultiMeshes(copy);
      return metaMesh;
    }

    public static MetaMesh BuildHolsterMeshWithWeapon(
      WeaponDesign craftedData,
      float pivotDiff,
      bool batchAllMeshes)
    {
      if (craftedData.Template.UseWeaponAsHolsterMesh)
        return (MetaMesh) null;
      WeaponDesignElement usedPiece1 = craftedData.UsedPieces[0];
      BladeData bladeData = usedPiece1.CraftingPiece.BladeData;
      if (string.IsNullOrEmpty(bladeData.HolsterMeshName))
        return (MetaMesh) null;
      MetaMesh metaMesh1 = MetaMesh.CreateMetaMesh();
      MetaMesh copy1 = MetaMesh.GetCopy(bladeData.HolsterMeshName, false, true);
      string str = bladeData.HolsterMeshName + "_skeleton";
      if (Skeleton.SkeletonModelExist(str))
      {
        MetaMesh metaMesh2 = CraftedDataView.BuildWeaponMesh(craftedData, 0.0f, true, batchAllMeshes);
        float num1 = craftedData.PiecePivotDistances[0] - craftedData.UsedPieces[0].ScaledDistanceToPreviousPiece;
        List<MetaMesh> metaMeshes = new List<MetaMesh>();
        Skeleton fromModel = Skeleton.CreateFromModel(str);
        for (sbyte boneIndex = 1; (int) boneIndex < (int) fromModel.GetBoneCount(); ++boneIndex)
        {
          MatrixFrame entitialRestFrame = fromModel.GetBoneEntitialRestFrame(boneIndex, false);
          if (craftedData.Template.RotateWeaponInHolster)
            entitialRestFrame.rotation.RotateAboutForward(3.14159274f);
          MetaMesh copy2 = metaMesh2.CreateCopy();
          MatrixFrame matrixFrame = new MatrixFrame(entitialRestFrame.rotation, entitialRestFrame.origin);
          matrixFrame.Elevate(-num1);
          copy2.Frame = matrixFrame;
          if (batchAllMeshes)
          {
            int num2 = 8 - ((int) boneIndex - 1);
            copy2.SetMaterial(Material.GetFromResource("weapon_crafting_quiver_deformer"));
            copy2.SetFactor1Linear((uint) (419430400UL * (ulong) num2));
            metaMeshes.Add(copy2);
          }
          else
            metaMesh1.MergeMultiMeshes(copy2);
        }
        if (metaMeshes.Count > 0)
          metaMesh1.BatchMultiMeshesMultiple(metaMeshes);
        if (craftedData.Template.PieceTypeToScaleHolsterWith != CraftingPiece.PieceTypes.Invalid)
        {
          WeaponDesignElement usedPiece2 = craftedData.UsedPieces[(int) craftedData.Template.PieceTypeToScaleHolsterWith];
          MatrixFrame frame = copy1.Frame;
          int num3 = -MathF.Sign(fromModel.GetBoneEntitialRestFrame((sbyte) 0, false).rotation.u.z);
          float num4 = (float) ((double) usedPiece1.CraftingPiece.BladeData.HolsterMeshLength * ((double) usedPiece2.ScaleFactor - 1.0) * 0.5) * (float) num3;
          WeaponDesignElement usedPiece3 = craftedData.UsedPieces[(int) craftedData.Template.PieceTypeToScaleHolsterWith];
          if (usedPiece3.IsPieceScaled)
          {
            Vec3 scalingVector = usedPiece3.CraftingPiece.FullScale ? Vec3.One * usedPiece3.ScaleFactor : new Vec3(1f, 1f, usedPiece3.ScaleFactor);
            frame.Scale(scalingVector);
          }
          frame.origin += new Vec3(z: -num4);
          copy1.Frame = frame;
        }
      }
      else
      {
        if (craftedData.Template.PieceTypeToScaleHolsterWith != CraftingPiece.PieceTypes.Invalid)
        {
          MatrixFrame frame = copy1.Frame;
          frame.origin += new Vec3(z: craftedData.PiecePivotDistances[(int) craftedData.Template.PieceTypeToScaleHolsterWith]);
          WeaponDesignElement usedPiece4 = craftedData.UsedPieces[(int) craftedData.Template.PieceTypeToScaleHolsterWith];
          if (usedPiece4.IsPieceScaled)
          {
            Vec3 scalingVector = usedPiece4.CraftingPiece.FullScale ? Vec3.One * usedPiece4.ScaleFactor : new Vec3(1f, 1f, usedPiece4.ScaleFactor);
            frame.Scale(scalingVector);
          }
          copy1.Frame = frame;
        }
        metaMesh1.MergeMultiMeshes(CraftedDataView.BuildWeaponMesh(craftedData, 0.0f, true, batchAllMeshes));
      }
      metaMesh1.MergeMultiMeshes(copy1);
      MatrixFrame frame1 = metaMesh1.Frame;
      frame1.origin += new Vec3(z: pivotDiff);
      metaMesh1.Frame = frame1;
      return metaMesh1;
    }
  }
}
